/// Socket服务类
/// 管理与服务器的WebSocket连接
library;
import 'package:socket_io_client/socket_io_client.dart' as IO;
import 'package:chat_project/config/api_config.dart';
import 'package:chat_project/services/storage_service.dart';
import 'package:flutter/widgets.dart';

typedef SocketEventCallback = void Function(dynamic data);

class SocketService {
  final StorageService _storageService = StorageService();
  IO.Socket? _socket;
  bool _isConnected = false;
  String? _userId;
  bool _isInitialized = false; // 添加初始化标志
  
  // 事件监听器
  final Map<String, List<SocketEventCallback>> _listeners = {};
  
  // 获取连接状态
  bool get isConnected => _isConnected;
  
  // 获取Socket实例
  IO.Socket? get socket => _socket;
  
  // 初始化Socket连接
  Future<void> init() async {
    // 如果已经初始化，则直接返回
    if (_isInitialized && _socket != null) {
      print('Socket已经初始化，正在检查连接状态...');
      if (!_isConnected) {
        reconnect();
      }
      return;
    }
    
    // 从存储中获取用户ID
    final user = await _storageService.getUser();
    if (user == null) {
      print('Socket初始化失败：用户未登录');
      return;
    }
    
    _userId = user.id;
    print('Socket初始化：用户ID = $_userId');
    
    // 获取令牌
    final token = await _storageService.getToken();
    if (token == null || token.isEmpty) {
      print('Socket初始化失败：令牌不存在');
      return;
    }
    
    print('Socket正在初始化：使用令牌 ${token.length > 10 ? token.substring(0, 10) : token}...');
    
    try {
      // 断开旧连接
      if (_socket != null) {
        _socket!.disconnect();
      }
      
      // 设置Socket选项
      final options = IO.OptionBuilder()
          .setTransports(['websocket']) // 优先使用WebSocket
          .enableForceNew() // 强制创建新连接
          .enableAutoConnect() // 自动连接
          .enableReconnection() // 启用自动重连
          .setReconnectionAttempts(10) // 最多重试10次
          .setReconnectionDelay(3000) // 3秒后重试
          .setExtraHeaders({
            'Authorization': 'Bearer $token',
            'Content-Type': 'application/json'
          })
          .setAuth({
            'token': token
          })
          .build();

      // 初始化Socket连接
      _socket = IO.io(ApiConfig.socketUrl, options);
      
      print('Socket选项已配置：${ApiConfig.socketUrl}');
      
      // 设置事件监听器
      _setupEventListeners();
      
      // 标记为已初始化
      _isInitialized = true;
      
      // 连接到服务器
      _socket?.connect();
      print('Socket连接请求已发送');
      
      // 监听所有事件（调试用）
      _socket?.onAny((event, data) {
        print('Socket收到事件: $event, 数据: $data');
        
        // 对于任何消息事件，都尝试以receive_message的形式转发
        if (event.contains('message') && event != 'message_status_update' && event != 'receive_message') {
          print('转发消息事件: $event -> receive_message');
          _triggerEvent('receive_message', data);
        }
      });
      
      // 设置心跳检测
      _startHeartbeat();
    } catch (e) {
      print('Socket初始化错误: $e');
    }
  }
  
  // 心跳检测，确保连接保持活跃
  void _startHeartbeat() {
    const interval = Duration(seconds: 30);
    Future.delayed(interval, () async {
      if (_socket != null && _isConnected) {
        // 发送心跳事件
        _socket?.emit('heartbeat', {'userId': _userId});
        print('发送心跳信号');
      } else if (_socket != null && !_isConnected) {
        // 尝试重连
        reconnect();
      }
      
      // 继续定时发送
      _startHeartbeat();
    });
  }
  
  // 设置基本事件监听器
  void _setupEventListeners() {
    _socket?.onConnect((_) {
      print('Socket已连接');
      _isConnected = true;
      
      // 发送用户连接事件，通知服务器用户上线
      _socket?.emit('user_connect', {'userId': _userId});
      
      // 触发已注册的连接事件
      _triggerEvent('connect', null);
    });
    
    _socket?.onDisconnect((_) {
      print('Socket已断开连接');
      _isConnected = false;
      
      // 触发已注册的断开连接事件
      _triggerEvent('disconnect', null);
      
      // 5秒后尝试重连
      Future.delayed(const Duration(seconds: 5), () {
        reconnect();
      });
    });
    
    _socket?.onConnectError((error) {
      print('Socket连接错误: $error');
      _isConnected = false;
      
      // 触发已注册的连接错误事件
      _triggerEvent('connect_error', error);
      
      // 尝试自动重连
      Future.delayed(const Duration(seconds: 3), () {
        if (!_isConnected && _socket != null) {
          print('Socket自动重连中...');
          _socket?.connect();
        }
      });
    });
    
    _socket?.onError((error) {
      print('Socket错误: $error');
      
      // 触发已注册的错误事件
      _triggerEvent('error', error);
    });
    
    // 监听在线用户列表更新
    _socket?.on('online_users', (data) {
      _triggerEvent('online_users', data);
    });
    
    // 监听用户状态变化
    _socket?.on('user_status_change', (data) {
      _triggerEvent('user_status_change', data);
    });
    
    // 监听接收消息 - 注册多个可能的事件名，以确保兼容性
    _socket?.on('receive_message', (data) {
      print('收到新消息(receive_message): $data');
      _triggerEvent('receive_message', data);
    });
    
    _socket?.on('message:receive', (data) {
      print('收到新消息(message:receive): $data');
      _triggerEvent('receive_message', data);
    });
    
    _socket?.on('new_message', (data) {
      print('收到新消息(new_message): $data');
      _triggerEvent('receive_message', data);
    });
    
    _socket?.on('message', (data) {
      print('收到新消息(message): $data');
      _triggerEvent('receive_message', data);
    });
    
    // 监听消息状态更新
    _socket?.on('message_status_update', (data) {
      _triggerEvent('message_status_update', data);
    });
    
    // 用户输入状态
    _socket?.on('typing:start', (data) {
      _triggerEvent('typing:start', data);
    });
    
    _socket?.on('typing:stop', (data) {
      _triggerEvent('typing:stop', data);
    });
  }
  
  // 发送消息
  void sendMessage(String senderId, String receiverId, String content, String type, {String? conversationId}) {
    if (!_isConnected) {
      print('Socket未连接，无法发送消息');
      // 在模拟模式下，我们可以假装发送成功
      if (_useMockData()) {
        print('模拟发送消息');
        return;
      }
      reconnect();
      return;
    }
    
    if (_socket == null) {
      print('Socket为空，无法发送消息');
      return;
    }
    
    // 确保senderId和receiverId是字符串并提取ID
    final String safeSenderId = _extractId(senderId);
    final String safeReceiverId = _extractId(receiverId);
    
    // 构建消息数据
    final Map<String, dynamic> messageData = {
      'senderId': safeSenderId,
      'receiverId': safeReceiverId,
      'content': content,
      'type': type
    };
    
    // 如果提供了conversationId，则添加到数据中
    if (conversationId != null && conversationId.isNotEmpty) {
      final String safeConversationId = _extractId(conversationId);
      messageData['conversationId'] = safeConversationId;
      print('发送消息: 使用会话ID=$safeConversationId, content=$content');
    } else {
      print('发送消息: senderId=$safeSenderId, receiverId=$safeReceiverId, content=$content, type=$type');
    }
    
    // 发送消息事件
    _socket?.emit('message:send', messageData);
  }
  
  // 标记消息为已读
  void markMessageAsRead(String messageId) {
    if (!_isConnected) {
      print('Socket未连接，无法标记消息已读');
      // 在模拟模式下，我们可以假装标记成功
      if (_useMockData()) {
        print('模拟标记消息已读');
        return;
      }
      reconnect();
      return;
    }
    
    if (_socket == null || _userId == null) {
      print('Socket或用户ID为空，无法标记消息已读');
      return;
    }
    
    _socket?.emit('message_read', {
      'messageId': messageId,
      'userId': _userId
    });
  }
  
  // 发送正在输入状态
  void sendTyping(String receiverId, bool isTyping) {
    if (!_isConnected) {
      print('Socket未连接，无法发送输入状态');
      // 在模拟模式下，我们可以假装发送成功
      if (_useMockData()) {
        print('模拟发送输入状态');
        return;
      }
      reconnect();
      return;
    }
    
    if (_socket == null || _userId == null) {
      print('Socket或用户ID为空，无法发送输入状态');
      return;
    }
    
    // 确保receiverId是一个简单字符串
    final String safeReceiverId = _extractId(receiverId);
    
    print('发送输入状态: senderId=$_userId, receiverId=$safeReceiverId, isTyping=$isTyping');
    final event = isTyping ? 'typing:start' : 'typing:stop';
    
    // 使用对话ID而非拼接字符串，防止MongoDB ObjectId验证错误
    _socket?.emit(event, {
      'senderId': _userId,
      'receiverId': safeReceiverId,
      // 不要在前端生成会话ID
      //'conversationId': 'conv_${safeReceiverId.replaceAll("user_", "")}'
    });
  }
  
  // 提取ID辅助方法
  String _extractId(String id) {
    if (id.contains('{') || id.contains('}') || id.contains(':')) {
      // 尝试提取ID
      final idMatch = RegExp(r"_id:\s*([^\s,}]+)").firstMatch(id);
      if (idMatch != null && idMatch.groupCount > 0) {
        final extractedId = idMatch.group(1)!.trim();
        print('从复杂对象中提取ID: $extractedId');
        return extractedId;
      } else {
        print('警告: 无法从复杂对象中提取ID，使用原始值: $id');
        return id;
      }
    }
    return id;
  }
  
  // 注册事件监听器
  void on(String event, SocketEventCallback callback) {
    if (!_listeners.containsKey(event)) {
      _listeners[event] = [];
    }
    _listeners[event]?.add(callback);
  }
  
  // 移除事件监听器
  void off(String event, [SocketEventCallback? callback]) {
    if (!_listeners.containsKey(event)) return;
    
    if (callback != null) {
      _listeners[event]?.remove(callback);
    } else {
      _listeners.remove(event);
    }
  }
  
  // 触发事件
  void _triggerEvent(String event, dynamic data) {
    if (!_listeners.containsKey(event)) return;
    
    try {
      // 立即在主线程上触发事件
      for (final callback in _listeners[event] ?? []) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          try {
            callback(data);
          } catch (e) {
            print('执行Socket回调错误: $e');
          }
        });
      }
    } catch (e) {
      print('触发事件错误: $e');
    }
  }
  
  // 断开连接
  void disconnect() {
    _socket?.disconnect();
    _isConnected = false;
    _userId = null;
  }
  
  // 重新连接
  void reconnect() async {
    print('尝试重新连接Socket...');
    
    // 如果已连接，则不需要重连
    if (_isConnected) {
      print('Socket已连接，无需重连');
      return;
    }
    
    if (_socket != null) {
      if (!_socket!.connected) {
        _socket?.connect();
        print('重新连接到现有Socket');
      }
    } else {
      await init();
      print('重新初始化Socket连接');
    }
  }
  
  // 检查是否使用模拟数据
  bool _useMockData() {
    // 可以在这里根据配置决定是否使用模拟数据
    return false;
  }
} 